`timescale 1ns/1ps
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2023 All rights reserved
// *********************************************************************************
// Project Name : 
// Author       : Dark
// Create Time  : 2023-02-04 13:58:10
// Revise Time	: 2023-02-04 13:58:10
// File Name    : riscv_core.sv
// Abstract     : core top
`include "defines.svh"
module riscv_core (
	input clk,    // Clock
	input rst_n,  // Synchronous reset active low
	output led
);

//=================================================================================
// Signal declaration
//=================================================================================

// system clk and reset
	logic			sys_clk			;
	logic			sys_rst_n		;
	logic			locked			;
// pc
	logic			zero            ;
	logic			less            ;
	logic	[3:0]	branch          ;
	logic	[31:0]	imm             ;

	logic	[31:0]	PC              ;
	logic	[31:0]	nextPC          ;
	logic	[31:0]	instr           ;
	logic			PCjump_flag		; 	//to irom address
	logic			PCjump_flag_pipe; 	//to irom address
// PIPE if2id
	logic	[31:0]	PC_if2id        ;	
	logic	[31:0]	instr_if2id     ;



// regbank
	logic	[4:0]	rs1_addr        ;   //rs1
	logic	[4:0]	rs2_addr        ;	//rs2
	logic	[4:0]	rd_addr         ;	//rd 


	logic	[31:0]	rs1_data        ;
	logic	[31:0]	rs2_data        ;
// PIPE id2ex
	logic	[31:0]	PC_id2ex		;
	// regbank address and data
	logic	[31:0]	rs1_data_id2ex	;
	logic	[31:0]	rs2_data_id2ex	;
	logic	[31:0]	rs1_data_id2ex_temp	;
	logic	[31:0]	rs2_data_id2ex_temp	;
	logic	[ 4:0]	rs1_id2ex 		;
	logic	[ 4:0]	rs2_id2ex 		;
	logic	[ 4:0]	rd_id2ex     	;
	logic	[31:0]	imm_id2ex		;
	// control signals
	logic			wb_en_id2ex 	;//Register bank write enable
	logic			alu_srcA_id2ex	;	//alu operand A
	logic	[ 1:0]	alu_srcB_id2ex	;	//alu operand B
	logic	[ 3:0]	alu_ctrl_id2ex	;	//alu control
	logic	[ 3:0]	branch_id2ex	;	// pc 
	logic			wb_src_id2ex	;	// 0 alu or 1 mem
	logic			mem_wr_id2ex	;	// data mem write enable 
	logic			mem_rd_id2ex	;  	// data mem read  enable 
	logic	[ 2:0]	mem_ctrl_id2ex 	;// data mem control signal		

	// control signals
	logic			alu_srcA		;	//alu operand A
	logic	[ 1:0]	alu_srcB		;	//alu operand B
	logic	[ 3:0]	alu_ctrl		;	//alu control
	logic			wb_src			;	// 0 alu or 1 mem
	logic			wb_en           ;
	logic			mem_wr 			;	// data mem write enable 
	logic			mem_rd 			;	// data mem write enable 
	logic	[ 2:0]	mem_ctrl		;	// data mem control signal
	// EXU result
	logic	[31:0]	alu_out			;
	logic	[31:0]	mem_out			;	
	logic	[31:0]	mem_din 		;
// PIPE ex2mem

	// write back register address
	logic	[31:0]	wb_data_ex2mem 	;
	logic	[ 4:0]	wb_addr_ex2mem 	;
	logic	[31:0]	rs2_data_ex2mem	;
	logic	[31:0]	alu_out_ex2mem 	;
	logic	[31:0]	mem_din_ex2mem	;
	// control signals
	logic			wb_en_ex2mem 	;//Register bank write enable
	logic			wb_src_ex2mem	;// 0 alu or 1 mem
	logic			mem_wr_ex2mem 	;// data mem write enable 
	logic			mem_rd_ex2mem 	;// data mem read  enable
	logic	[ 2:0]	mem_ctrl_ex2mem ;	// data mem control signal	
// PIPE mem2wb
	logic	[4:0]	wb_addr_mem2wb 	;	//rd
	logic	[31:0]	wb_data_mem2wb 	;
	logic			wb_en_mem2wb	;
// Forward and Hazard Unit
	logic			refetch_flag 	;
//=================================================================================
// Body
//=================================================================================
	assign	sys_rst_n = rst_n&locked;
	assign 	led = PC[2];

//-------------------------------------------------------------------------------------
//The first level of the pipeline  pc and fetch 
//-------------------------------------------------------------------------------------

	pc_gen inst_pc_gen
		(
			.clk			(sys_clk), 
			.rst_n			(sys_rst_n), 
		// input
			.zero     		(zero),
			.less     		(less),
			.branch   		(branch_id2ex),
			.imm      		(imm_id2ex),
			.rs1_data 		(rs1_data_id2ex),
			.PC_id2ex   	(PC_id2ex),
			.PC  			(PC),
			.rs1_if2id    	(rs1_addr),
			.rs2_if2id    	(rs2_addr),
			.rd_id2ex     	(rd_id2ex),
			.mem_rd_id2ex 	(mem_rd_id2ex),
		// output
			.refetch_flag  	(refetch_flag),
			.PCjump_flag	(PCjump_flag),
			.PCjump_flag_pipe(PCjump_flag_pipe),
			.nextPC   		(nextPC)
		);
		
	
	ifetch inst_ifetch 
		(
		// input
			.clk			(sys_clk), 
			.rst_n			(sys_rst_n), 
			.nextPC			(nextPC),
			.refetch_flag	(refetch_flag),
		// output
			.PC 			(PC), 
			.instr 			(instr));

//-------------------------------------------------------------------------------------
//The second level of the pipeline  IF2ID
//-------------------------------------------------------------------------------------
	if2id inst_if2id
		(
			.clk         	(sys_clk),
			.rst_n       	(sys_rst_n),
			.PC          	(PC),
			.instr       	(instr),
			.refetch_flag	(refetch_flag),
			.PCjump_flag_pipe(PCjump_flag_pipe),

			.PC_if2id    	(PC_if2id),
			.instr_if2id 	(instr_if2id)
		);
//-------------------------------------------------------------------------------------
//The third level of the pipeline  ID2EX
//-------------------------------------------------------------------------------------



	ctrl_gen inst_ctrl_gen
		(
			.instr    		(instr_if2id),
	
			.wb_en   		(wb_en),
			.alu_srcA 		(alu_srcA),
			.alu_srcB 		(alu_srcB),
			.alu_ctrl 		(alu_ctrl),
			.branch   		(branch),
			.wb_src  		(wb_src),
			.mem_wr  		(mem_wr),
			.mem_rd   		(mem_rd),
			.mem_ctrl 		(mem_ctrl)
		);
//	32 regbank



	assign  rs1_addr   		= instr_if2id[19:15];
	assign  rs2_addr   		= instr_if2id[24:20];
	assign  rd_addr    		= instr_if2id[11:7]	;
	regfile inst_regfile
		(
			.clk      		(sys_clk),
			.rst_n    		(sys_rst_n),
			.rs1_addr 		(rs1_addr),
			.rs2_addr 		(rs2_addr),
			.wb_addr 		(wb_addr_mem2wb),
			.wb_data 		(wb_data_mem2wb),
			.wb_en   		(wb_en_mem2wb),

			.rs1_data 		(rs1_data),
			.rs2_data 		(rs2_data)
		);
	imm_gen inst_imm_gen
		(
			.instr 			(instr_if2id), 

			.imm 			(imm));

	id2ex inst_id2ex
		(
			.clk            (sys_clk),
			.rst_n          (sys_rst_n),
			.PC  		    (PC_if2id),
			.rs1            (rs1_addr),
			.rs2            (rs2_addr),
			.rd             (rd_addr),
			.rs1_data       (rs1_data),
			.rs2_data       (rs2_data),
			.imm            (imm),
			.alu_out 		(alu_out),
			.wb_addr_ex2mem	(wb_addr_ex2mem),
			.wb_en_ex2mem	(wb_en_ex2mem),
			.alu_out_ex2mem	(alu_out_ex2mem),

			.alu_srcA       (alu_srcA),
			.alu_srcB       (alu_srcB),
			.alu_ctrl       (alu_ctrl),
			.branch         (branch),
			.wb_en         	(wb_en),
			.wb_src        	(wb_src),
			.mem_wr         (mem_wr),
			.mem_rd         (mem_rd),
			.mem_ctrl       (mem_ctrl),
			.refetch_flag   (refetch_flag),
			.PCjump_flag    (PCjump_flag),

			.PC_id2ex    	(PC_id2ex),
			.rs1_data_id2ex (rs1_data_id2ex_temp),
			.rs2_data_id2ex (rs2_data_id2ex_temp),
			.rs1_id2ex      (rs1_id2ex),
			.rs2_id2ex      (rs2_id2ex),
			.rd_id2ex       (rd_id2ex),
			.imm_id2ex      (imm_id2ex),
			.wb_en_id2ex   	(wb_en_id2ex),
			.alu_srcA_id2ex (alu_srcA_id2ex),
			.alu_srcB_id2ex (alu_srcB_id2ex),
			.alu_ctrl_id2ex (alu_ctrl_id2ex),
			.branch_id2ex   (branch_id2ex),
			.wb_src_id2ex  	(wb_src_id2ex),
			.mem_wr_id2ex   (mem_wr_id2ex),
			.mem_rd_id2ex   (mem_rd_id2ex),
			.mem_ctrl_id2ex (mem_ctrl_id2ex)
		);

//-------------------------------------------------------------------------------------
//The fourth level of the pipeline  EX2MEM
//-------------------------------------------------------------------------------------

//  LOAD sturcture hazard
	assign	rs1_data_id2ex  = (wb_addr_mem2wb == rs1_id2ex
				&&wb_en_mem2wb&&wb_addr_mem2wb!=5'd0
				&&(wb_addr_ex2mem != rs1_id2ex||!wb_en_ex2mem)) ? wb_data_mem2wb : rs1_data_id2ex_temp;
	assign	rs2_data_id2ex  = (wb_addr_mem2wb == rs2_id2ex
				&&wb_en_mem2wb&&wb_addr_mem2wb!=5'd0
				&&(wb_addr_ex2mem != rs2_id2ex||!wb_en_ex2mem)) ? wb_data_mem2wb : rs2_data_id2ex_temp;
	exu inst_exu
		(
			.imm            (imm_id2ex),
			.alu_srcA       (alu_srcA_id2ex),
			.alu_srcB       (alu_srcB_id2ex),
			.alu_ctrl       (alu_ctrl_id2ex),
			.PC             (PC_id2ex),
			.rs1_data       (rs1_data_id2ex),
			.rs2_data       (rs2_data_id2ex),

			.alu_out        (alu_out),
			.zero           (zero),
			.less           (less)
		);


	ex2mem inst_ex2mem
		(
			.clk             	(sys_clk),
			.rst_n           	(sys_rst_n),
			.rd              	(rd_id2ex),
			.alu_out         	(alu_out),
			.wb_src         	(wb_src_id2ex),
			.wb_en          	(wb_en_id2ex),
			.mem_wr          	(mem_wr_id2ex),
			.mem_rd          	(mem_rd_id2ex),
			.mem_ctrl        	(mem_ctrl_id2ex),
			.mem_din   	     	(rs2_data_id2ex),// Store,rs2 need forward too

			.wb_addr_ex2mem  	(wb_addr_ex2mem),
			.alu_out_ex2mem  	(alu_out_ex2mem),
			.wb_en_ex2mem   	(wb_en_ex2mem),
			.wb_src_ex2mem  	(wb_src_ex2mem),
			.mem_wr_ex2mem   	(mem_wr_ex2mem),
			.mem_rd_ex2mem 		(mem_rd_ex2mem),
			.mem_ctrl_ex2mem	(mem_ctrl_ex2mem),
			.mem_din_ex2mem 	(mem_din_ex2mem)
		);

//-------------------------------------------------------------------------------------
//The fifth level of the pipeline  MEM2WB
//-------------------------------------------------------------------------------------
	dtcm inst_dtcm
			(
				.clk      	(sys_clk),
				.rst_n    	(sys_rst_n),
				.wren     	(mem_wr_ex2mem),
				.rden     	(mem_rd_ex2mem),
				.mem_ctrl 	(mem_ctrl_ex2mem),
				.addr     	(alu_out_ex2mem),
				.din      	(mem_din_ex2mem),
	
				.dout     	(mem_out)
			);


	mem2wb inst_mem2wb
		(
			.clk            (sys_clk),
			.rst_n          (sys_rst_n),
			.wb_addr        (wb_addr_ex2mem),
			.alu_out        (alu_out_ex2mem),
			.mem_out        (mem_out),
			.wb_en         	(wb_en_ex2mem),
			.wb_src        	(wb_src_ex2mem),

			.wb_addr_mem2wb (wb_addr_mem2wb),
			.wb_data_mem2wb (wb_data_mem2wb),
			.wb_en_mem2wb   (wb_en_mem2wb)
		);
		
		
		
	clk_wiz_0 clk_100M_out
   (
    // Clock out ports
    .clk_out1(sys_clk),     // output clk_out1
    // Status and control signals
    .resetn(rst_n), // input resetn
    .locked(locked),       // output locked
   // Clock in ports
    .clk_in1(clk));      // input clk_in1
endmodule : riscv_core

